package com.rede.didiok.user.service.impl;

import java.util.*;

import javax.annotation.Resource;

import cn.hutool.core.bean.BeanUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rede.didiok.common.constant.conf.MessageConf;
import com.rede.didiok.common.constant.conf.SQLConf;
import com.rede.didiok.common.constant.conf.SysConf;
import com.rede.didiok.common.constant.global.Constants;
import com.rede.didiok.common.domainEvent.EventAction;
import com.rede.didiok.common.dto.user.EmoticonDto;
import com.rede.didiok.common.enums.StatusEnum;
import com.rede.didiok.common.exception.exceptionType.DeleteException;
import com.rede.didiok.common.exception.exceptionType.QueryException;
import com.rede.didiok.common.exception.exceptionType.UpdateException;
import com.rede.didiok.common.holder.RequestHolder;
import com.rede.didiok.common.utils.ResultUtil;
import com.rede.didiok.common.utils.StringUtils;
import com.rede.didiok.common.utils.business.DomainEventUtil;
import com.rede.didiok.common.utils.business.FileFeignUtil;
import com.rede.didiok.user.dao.EmoticonDao;
import com.rede.didiok.user.entity.EmoticonEntity;
import com.rede.didiok.user.service.EmoticonService;


@Service("emoticonService")
public class EmoticonServiceImpl extends ServiceImpl<EmoticonDao, EmoticonEntity> implements EmoticonService {


    @Resource
    private FileFeignUtil fileFeignUtil;
    @Resource
    private DomainEventUtil domainEventUtil;

    /***************************** admin:start **************************/
    // region  didiok-admin

    // endregion
    /***************************** admin:end **************************/



    /***************************** web:start **************************/
    // region didiok-web

    @Override
    public IPage<EmoticonEntity> getPageList(EmoticonDto emoticonDto) {
        QueryWrapper<EmoticonEntity> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(emoticonDto.getCreateUserUid())) {
            queryWrapper.eq(SQLConf.CREATE_USER_UID, emoticonDto.getCreateUserUid());
        }

        if (StringUtils.isNotEmpty(emoticonDto.getIsSelection())) {
            queryWrapper.eq(SQLConf.IS_SELECTION, emoticonDto.getIsSelection());
        }
        Page<EmoticonEntity> page = new Page<>();
        page.setCurrent(emoticonDto.getCurrentPage());
        page.setSize(emoticonDto.getPageSize());
        queryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        if (StringUtils.isNotEmpty(emoticonDto.getOrderByAscColumn())) {
            // 将驼峰转换成下划线
            String column = StringUtils.underLine(new StringBuffer(emoticonDto.getOrderByAscColumn())).toString();
            queryWrapper.orderByAsc(column);
        } else if (StringUtils.isNotEmpty(emoticonDto.getOrderByDescColumn())) {
            // 将驼峰转换成下划线
            String column = StringUtils.underLine(new StringBuffer(emoticonDto.getOrderByDescColumn())).toString();
            queryWrapper.orderByDesc(column);
        } else {
            queryWrapper.orderByDesc(SQLConf.SORT, SQLConf.CREATE_TIME);
        }
        IPage<EmoticonEntity> pageList = this.page(page, queryWrapper);
        List<String> fileUidList = new ArrayList<>();
        List<EmoticonEntity> emoticonList = pageList.getRecords();
        emoticonList.forEach(item -> {
            if (StringUtils.isNotEmpty(item.getFileUid())) {
                fileUidList.add(item.getFileUid());
            }
        });
        // 设置表情包
        Map<String, String> pictureMap = fileFeignUtil.fileUidToFileUrlMap(fileUidList);
        emoticonList.forEach(item -> {
            if (StringUtils.isNotEmpty(item.getFileUid())) {
                item.setPhotoUrl(pictureMap.get(item.getFileUid()));
            }
        });
        return pageList;
    }


    @Override
    public String addEmoticon(EmoticonDto emoticonDto) {
        String userUid = RequestHolder.getUserUid();
        if (StringUtils.isEmpty(userUid)) {
            throw new QueryException(Constants.USER_UID_EMPTY);
        }
        // 添加前，判断表情包是否存在
        QueryWrapper<EmoticonEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        queryWrapper.eq(SQLConf.FILE_UID, emoticonDto.getFileUid());
        queryWrapper.eq(SQLConf.CREATE_USER_UID, userUid);
        Integer count = this.count(queryWrapper);
        if (count > 0) {
            return ResultUtil.errorWithMessage("添加失败，该表情包已存在！");
        }
        emoticonDto.setCreateUserUid(userUid);
        EmoticonEntity emoticon = new EmoticonEntity();
        BeanUtil.copyProperties(emoticonDto, emoticon, SysConf.STATUS);
        boolean isSave = emoticon.insert();
        if (isSave) {
            domainEventUtil.publishEvent(EventAction.EMOTICON_ADD, emoticon);
        }
        return ResultUtil.successWithMessage(MessageConf.INSERT_SUCCESS);
    }

    @Override
    public String stickyEmoticon(EmoticonDto emoticonDto) {
        EmoticonEntity emoticon = this.getById(emoticonDto.getUid());
        if (emoticon == null) {
            log.error("置顶失败，表情包不存在");
            throw new UpdateException("置顶失败，表情包不存在");
        }
        // 查询到排名最前的表情包
        QueryWrapper<EmoticonEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(SQLConf.STATUS, StatusEnum.ENABLE);
        queryWrapper.orderByDesc(SQLConf.SORT);
        queryWrapper.last(SysConf.LIMIT_ONE);
        EmoticonEntity maxEmoticon = this.getOne(queryWrapper);
        // 比最大的还要大
        if (maxEmoticon != null) {
            // 如果第一名是自己
            if (maxEmoticon.getUid().equals(emoticon.getUid())) {
                return ResultUtil.errorWithMessage("该表情包已在最前！");
            }
            emoticon.setSort(maxEmoticon.getSort() + 1);
        } else {
            emoticon.setSort(1);
        }
        boolean isSave = emoticon.updateById();
        if (isSave) {
            domainEventUtil.publishEvent(EventAction.EMOTICON_STICKY, emoticon);
        }
        return ResultUtil.successWithMessage("置顶表情包成功");
    }

    @Override
    public String deleteBatchEmoticon(List<EmoticonDto> emoticonDtoList) {
        String userUid = RequestHolder.getUserUid();
        if (emoticonDtoList.size() == 0) {
            return ResultUtil.errorWithMessage(MessageConf.PARAM_INCORRECT);
        }
        List<String> uids = new ArrayList<>();
        emoticonDtoList.forEach(item -> {
            uids.add(item.getUid());
        });

        Collection<EmoticonEntity> tagList = this.listByIds(uids);
        tagList.forEach(item -> {
            if (!userUid.equals(item.getCreateUserUid())) {
                log.error("您无法删除其它人的表情包");
                throw new DeleteException("您无法删除其它人的表情包");
            }
            item.setUpdateTime(new Date());
            item.setStatus(StatusEnum.DISABLED);
            // 发送删除表情包领域事件
            domainEventUtil.publishEvent(EventAction.EMOTICON_DELETE, item);
        });
        boolean save = this.updateBatchById(tagList);
        if (save) {
            return ResultUtil.successWithMessage(MessageConf.DELETE_SUCCESS);
        } else {
            return ResultUtil.errorWithMessage(MessageConf.DELETE_FAIL);
        }
    }
    // endregion
    /***************************** web:end **************************/

    @Override
    public String editEmoticon(EmoticonDto emoticonDto) {
        EmoticonEntity emoticon = this.getById(emoticonDto.getUid());
        if (emoticon == null) {
            log.error("更新失败，表情包不存在");
            throw new UpdateException("更新失败，表情包不存在");
        }
        // 插入数据【使用Spring工具类提供的深拷贝】
        BeanUtils.copyProperties(emoticonDto, emoticon, SysConf.STATUS, SysConf.UID);
        emoticon.setUpdateTime(new Date());
        boolean isSave = emoticon.updateById();
        if (isSave) {
            domainEventUtil.publishEvent(EventAction.EMOTICON_EDIT, emoticon);
        }
        return ResultUtil.successWithMessage(MessageConf.UPDATE_SUCCESS);
    }

}